package gonet

import (
	"gitee.com/zhouhailin/gopkg/gostrings"
	"net"
	"strings"
)

// IpAddr IP地址
type IpAddr struct {
	Name     string
	IpV4s    []string
	IpV6s    []string
	HwAddr   string
	Up       bool
	Loopback bool
}

// IpV4 获取第一个IPv4地址
func (ipAddr *IpAddr) IpV4() string {
	if len(ipAddr.IpV4s) > 0 {
		return ipAddr.IpV4s[0]
	}
	return ""
}

// IpV6 获取第一个IPv6地址
func (ipAddr *IpAddr) IpV6() string {
	if len(ipAddr.IpV6s) > 0 {
		return ipAddr.IpV6s[0]
	}
	return ""
}

// GetIpV4ByName 获取指定名称的IPv4地址
func GetIpV4ByName(name string) *IpAddr {
	for _, addr := range *localIpAddrs() {
		if addr.Name == name && addr.Up && len(addr.IpV4s) > 0 {
			return &addr
		}
	}
	return nil
}

// GetIpV6ByName 获取指定名称的IPv6地址
func GetIpV6ByName(name string) *IpAddr {
	for _, addr := range *localIpAddrs() {
		if addr.Name == name && addr.Up && len(addr.IpV6s) > 0 {
			return &addr
		}
	}
	return nil
}

// ListIpV4s 获取所有IPv4地址
func ListIpV4s() *[]IpAddr {
	var ipAddrs []IpAddr
	for _, addr := range *localIpAddrs() {
		if addr.Up && len(addr.IpV4s) > 0 {
			ipAddrs = append(ipAddrs, addr)
		}
	}
	return &ipAddrs
}

// ListIpV6s 获取所有IPv6地址
func ListIpV6s() *[]IpAddr {
	var ipAddrs []IpAddr
	for _, addr := range *localIpAddrs() {
		if addr.Up && len(addr.IpV6s) > 0 {
			ipAddrs = append(ipAddrs, addr)
		}
	}
	return &ipAddrs
}

// localIpAddrs 获取本地IP地址
func localIpAddrs() *[]IpAddr {
	interfaces, err := net.Interfaces()
	if err != nil {
		return nil
	}
	var ipAddrs []IpAddr
	for _, intf := range interfaces {
		addrs, err := intf.Addrs()
		if err != nil {
			continue
		}
		var ipV4s []string
		var ipV6s []string
		for _, addr := range addrs {
			ipV4, ipV6 := getIpNetAddr(addr)
			if ipV4 != "" {
				ipV4s = append(ipV4s, ipV4)
			}
			if ipV6 != "" {
				ipV6s = append(ipV6s, ipV6)
			}
		}
		if len(ipV4s) == 0 && len(ipV6s) == 0 {
			continue
		}
		lo := false
		if len(ipV4s) > 0 {
			// lo : inet 127.0.0.1
			lo = strings.HasPrefix(ipV4s[0], "127")
		}
		if len(ipV6s) > 0 {
			// lo : inet6 ::1
			lo = strings.HasPrefix(ipV6s[0], "::1")
		}
		ipAddrs = append(ipAddrs, IpAddr{
			Name:     intf.Name,
			IpV4s:    ipV4s,
			IpV6s:    ipV6s,
			HwAddr:   intf.HardwareAddr.String(),
			Up:       intf.Flags&net.FlagUp != 0,
			Loopback: lo,
		})
	}
	return &ipAddrs
}

// getIpNetAddr 获取IP地址
func getIpNetAddr(addr net.Addr) (string, string) {
	if ipNet, ok := addr.(*net.IPNet); ok {
		if ipNet.IP.To4() != nil {
			return ipNet.IP.String(), gostrings.EMPTY
		} else if ipNet.IP.To16() != nil {
			return gostrings.EMPTY, ipNet.IP.String()
		} else {
			return gostrings.EMPTY, gostrings.EMPTY
		}
	}
	return gostrings.EMPTY, gostrings.EMPTY
}
